<html lang="en">
	<head>
		<title>4D Demo</title>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0">
		<style>
			body {
				color: #ffffff;
				font-family:Monospace;
				font-size:13px;
				text-align:center;
				font-weight: bold;

				background-color: #050505;
				margin: 0px;
				overflow: hidden;
			}

			#info {
				position: absolute;
				top: 0px; width: 100%;
				padding: 5px;
			}

			a {
				color: #ffffff;
			}

			#oldie a { color:#da0 }
		</style>
	</head>
	<body>
		<div id="container">
			<div>4D</div>
			0.0<img id="transferFunctionImg" style="align:right"/>1.0
		</div>
		<script src="js/three.min.js"></script>
		<script src="js/Detector.js"></script>
		<script src="js/stats.min.js"></script>
		<script src="js/OrbitControls.js"></script>
		<script src="js/PollutionCurve.js"></script>
		<script src="js/PollutionPoint.js"></script>
		<script src="js/PollutionVol.js"></script>
		<script src="js/Terrain.js"></script>
		<script src="js/dat.gui.js"></script>

		<script>
			if ( ! Detector.webgl ) Detector.addGetWebGLMessage();

			var container, stats;
			var camera, sceneFirstPass, sceneSecondPass, renderer, linegroup, pointgroup;
			var poslist1 = [];
			var poslist2 = [];
			var poslist3 = [];

			var plptlist = [];

			var clock = new THREE.Clock();
			var rtTexture, transferTexture;
			var histogram = [];
			var guiControls;
			var modeuiControls;
			var vol;

			init();
			animate();

			function init() {

				//Parameters that can be modified.
				guiControls = new function() {

					this.model = 'PM10';
					this.xmin = 0.0;
					this.xmax = 1.0;
					this.ymin = 0.0;
					this.ymax = 1.0;
					this.zpos = 1.0;
					this.cull = 0.0;
					this.intensity = 1.0;
				};

				modeuiControls = new function() {
					this.displayLine = false;
					this.displayPoint = false;
					this.displayVol = true;
				}

				container = document.getElementById( 'container' );

				camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 0.01, 3000.0 );
			    camera.position.set(1.7, 1.0, 2.0);
    			camera.up.set(0, 1, 0);

				controls = new THREE.OrbitControls( camera, container );

				var transferTexture = updateTransferFunction();

				var screenSize = new THREE.Vector2( window.innerWidth, window.innerHeight );
				rtTexture = new THREE.WebGLRenderTarget( screenSize.x, screenSize.y,
														{ 	minFilter: THREE.LinearFilter,
															magFilter: THREE.LinearFilter,
															wrapS:  THREE.ClampToEdgeWrapping,
															wrapT:  THREE.ClampToEdgeWrapping,
															format: THREE.RGBFormat,
															type: THREE.FloatType,
															generateMipmaps: false} );

				vol = new PollutionVol(rtTexture);

				sceneFirstPass = new THREE.Scene();
				sceneSecondPass = new THREE.Scene();
				sceneFirstPass.add( vol.createFirstPassMesh() );
				sceneSecondPass.add( vol.createSecondPassMesh() );

				var terrain = new Terrain(sceneSecondPass);
				terrain.load();
				sceneSecondPass.add(new THREE.AmbientLight(0x111111));

		        var light = new THREE.DirectionalLight(0xffffff, 2);
		        light.shadowCameraVisible = true;
		        light.position.set(0,300,100);
		        sceneSecondPass.add(light);

				renderer = new THREE.WebGLRenderer({ devicePixelRatio: 1.0 });
				container.appendChild( renderer.domElement );

				stats = new Stats();
				stats.domElement.style.position = 'absolute';
				stats.domElement.style.top = '0px';
				container.appendChild( stats.domElement );

				initUI();
				onWindowResize();
				initPoslist();

				window.addEventListener( 'resize', onWindowResize, false );
			}

			function initUI()
			{
				var gui = new dat.GUI();
				var modelSelected = gui.add(guiControls, 'model', [ 'PM10', 'PM2_5', 'SO2', 'NO2', 'CO', 'NO' ] );
				gui.add(guiControls, 'xmin', 0.0, 1.0).step(0.01).name("纬度");
				gui.add(guiControls, 'xmax', 0.0, 1.0).step(0.01).name("纬度");
				gui.add(guiControls, 'ymin', 0.0, 1.0).step(0.01).name("经度");
				gui.add(guiControls, 'ymax', 0.0, 1.0).step(0.01).name("经度");
				gui.add(guiControls, 'zpos', 0.0, 1.0).step(0.01).name("高度");
				gui.add(guiControls, 'cull', 0.0, 1.0).step(0.01).name("剔除");
				gui.add(guiControls, 'intensity', 0.0, 1.0).step(0.01).name("强度");
				modelSelected.onChange(function(value) {
					vol.changeVol(value);
				});

				var modegui = new dat.GUI();
				modegui.add(modeuiControls, 'displayVol', false).name("污染物").onChange(function(value) {
					vol.setVisible(value);
				});
				modegui.add(modeuiControls, 'displayLine', false).name("轨迹线").onChange(function(value) {
					linegroup.visible = value;
				});
				modegui.add(modeuiControls, 'displayPoint', false).name("运动线").onChange(function(value) {
					pointgroup.visible = value;
				});
			}

			function updateTransferFunction()
			{
				var canvas = document.createElement('canvas');
				canvas.height = 20;
				canvas.width = 256;

				var ctx = canvas.getContext('2d');

				var grd = ctx.createLinearGradient(0, 0, canvas.width -1 , canvas.height - 1);
				grd.addColorStop(0, "#78b800");
				grd.addColorStop(0.16, "#F9B516");
				grd.addColorStop(0.29, "#C57801");
				grd.addColorStop(0.41, "#EA121A");
				grd.addColorStop(0.59, "#B3055A");
				grd.addColorStop(0.88, "#600202");

				ctx.fillStyle = grd;
				ctx.fillRect(0,0,canvas.width -1 ,canvas.height -1 );

				var img = document.getElementById("transferFunctionImg");
				img.src = canvas.toDataURL();
				img.style.width = "256 px";
				img.style.height = "128 px";

				transferTexture =  new THREE.Texture(canvas);
				transferTexture.wrapS = transferTexture.wrapT =  THREE.ClampToEdgeWrapping;
				transferTexture.needsUpdate = true;

				return transferTexture;
			}

			function onWindowResize( event ) {

				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();

				renderer.setSize( window.innerWidth, window.innerHeight );
			}

			/**
			 * 向数组poslist添加三维点
			 * @param x
			 * @param y
             * @param z
             * @param poslist
             */
			function calPos(x,y,z, poslist)
			{
				var cenlat = 35.5862;
				// var cenlon = 108.191;
				var cenlon = 116.191;
				var newx = (parseFloat( x ) - cenlat)  / (311*3/111);
				var newy = (parseFloat( y ) - cenlon) / (203*3/91);
				var newz = parseFloat(z) * 0.0005 - 0.28;
				poslist.push(new THREE.Vector3(newx, newz, newy));
			}

			function initPoslist() {

				var loader = new THREE.FileLoader();
				var scpoe = this;
				//load a text file a output the result to the console
				loader.load('data',
				    function ( data ) {
				        var lines = data.split( '\n' );
						for ( var i = 0; i < lines.length; i+=3 ) {

							result1 = lines[i].split(',');
							calPos(parseFloat(result1[ 0 ]), parseFloat( result1[1] ), parseFloat( result1[2] ), poslist1);

							result2 = lines[i+1].split(',');
							calPos(parseFloat(result2[ 0 ]), parseFloat( result2[1] ), parseFloat( result2[2] ),poslist2);

							result3 = lines[i+2].split(',');
							calPos(parseFloat(result3[ 0 ]), parseFloat( result3[1] ), parseFloat( result3[2] ), poslist3);
						}

						createLine();
						createPoint();
				    }
				);
			}

			function createLine() {

				linegroup = new THREE.Group();
				var line1 = new PollutionCurve(poslist1, 0xff0000);
				linegroup.add(line1.createGeometry());

				var line2 = new PollutionCurve(poslist2, 0x00ff00);
				linegroup.add(line2.createGeometry());

				var line3 = new PollutionCurve(poslist3, 0x0000ff);
				linegroup.add(line3.createGeometry());

				linegroup.visible = false;
				sceneSecondPass.add(linegroup);
			}

			function createPoint() {

				pointgroup = new THREE.Group();
				var pt1 = new PollutionPoint(poslist1, 0xff0000);
				pointgroup.add(pt1.createPoint());
				plptlist.push(pt1);

				var pt2 = new PollutionPoint(poslist2, 0x00ff00);
				pointgroup.add(pt2.createPoint());
				plptlist.push(pt2);

				var pt3 = new PollutionPoint(poslist3, 0x0000ff);
				pointgroup.add(pt3.createPoint());
				plptlist.push(pt3);

				pointgroup.visible = false;
				sceneSecondPass.add(pointgroup);
			}


			function animate() {

				requestAnimationFrame( animate );

				if(pointgroup.visible)
				{
					for(var i = 0; i < plptlist.length; i++)
					{
						plptlist[i].move();
					}
				}

				render();
				stats.update();
			}


			function render() {

				var delta = clock.getDelta();

				//Render first pass and store the world space coords of the back face fragments into the texture.
				renderer.render( sceneFirstPass, camera, rtTexture, true );

				//Render the second pass and perform the volume rendering.
				renderer.render( sceneSecondPass, camera );

				if(vol.isVisible())
				{
					vol.setXMin(guiControls.xmin);
					vol.setXMax(guiControls.xmax);
					vol.setYMin(guiControls.ymin);
					vol.setYMax(guiControls.ymax);
					vol.setZPos(guiControls.zpos);
					vol.setCull(guiControls.cull);
					vol.setIntensity(guiControls.intensity);

					vol.render();
				}

			}
			
		</script>

	</body>
</html>
